package me.boot.db.mybatis.interceptor.datascope;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.experimental.UtilityClass;
import me.boot.common.data.model.DataPermissionInfo;
import me.boot.common.data.model.OwnerInfo;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.AllTableColumns;
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
import net.sf.jsqlparser.statement.select.SelectItem;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description:
 * @author: Sylar
 * @date: 2021年11月25日 10:33 上午
 */
@UtilityClass
public class DataScopeUtil {

    public void fieldFilter(List<SelectItem> selectItems, DataPermissionInfo dataPermissionInfo) {
        List<String> includeColumns = dataPermissionInfo.getIncludeColumns();
        List<String> excludeColumns = dataPermissionInfo.getExcludeColumns();

        List<SelectItem> removeItems = new ArrayList<>();
        if (CollUtil.isNotEmpty(selectItems)
                && (CollUtil.isNotEmpty(includeColumns) || CollUtil.isNotEmpty(excludeColumns))) {
            for (SelectItem selectItem : selectItems) {
                // 暂不处理其他类型的selectItem
                if (selectItem instanceof SelectExpressionItem) {
                    SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem;
                    Alias alias = selectExpressionItem.getAlias();
                    if ((CollUtil.isNotEmpty(includeColumns) && !includeColumns.contains(alias.getName()))
                            || (!CollUtil.isEmpty(excludeColumns) && excludeColumns.contains(alias.getName()))) {
                        removeItems.add(selectItem);
                    }
                } else if (selectItem instanceof AllTableColumns) {
                    removeItems.add(selectItem);
                }
            }
            if (CollectionUtils.isNotEmpty(removeItems)) {
                selectItems.removeAll(removeItems);
            }
        }
    }


    public Expression byOrg(List<Long> departmentIds) {
        Assert.notEmpty(departmentIds);
        ExpressionList expressionList = new ExpressionList();
        departmentIds.forEach(deptId -> expressionList.addExpressions(new LongValue(deptId)));
        InExpression inExpression = new InExpression();
        inExpression.setLeftExpression(new StringValue(OwnerInfo.FIELD_USER_ID));
        inExpression.setRightItemsList(expressionList);
        return inExpression;
    }

    public Expression byUser(Long userId) {
        Assert.notNull(userId);
        EqualsTo equalsTo = new EqualsTo();
        equalsTo.setLeftExpression(new StringValue(OwnerInfo.FIELD_USER_ID));
        equalsTo.setRightExpression(new StringValue(String.valueOf(userId)));
        return equalsTo;
    }

    public Expression byCustomize(String customExpression) {
        Assert.isTrue(StrUtil.isNotEmpty(customExpression), "没有配置自定义表达式");
        Expression expression = null;
        try {
            expression = CCJSqlParserUtil.parseCondExpression(customExpression);
        } catch (JSQLParserException ignored) {
        }
        Assert.notNull(expression, "自定义表达式配置错误:" + customExpression);
        return expression;
    }
}
